#pragma once

#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<string>
#include<vector>
#include<semaphore.h>
using namespace std;


//基于二向信号的生产消费者环形队列
const int CAP = 8;

template<class T>
class RingQueue
{
private:
     vector<T> _q;
     int _cap;//容量
     int _p_pos;//生产者位置
     int _c_pos;//消费者位置
     sem_t _blank_sem;//空间信号量
     sem_t _data_sem; //数据信号量

private:
    void P(sem_t& s)
    {
        sem_wait(&s);
    }

    void V(sem_t& s)
    {
        sem_post(&s);
    }

public:
    RingQueue(int num = CAP)
    :_cap(CAP),
    _p_pos(0),
    _c_pos(0)
    {
        _q.resize(CAP);
        sem_init(&_blank_sem, 0, _cap);
        sem_init(&_data_sem, 0, _cap);
    }

    ~RingQueue()
    {
        sem_destroy(&_blank_sem);
        sem_destroy(&_data_sem);
        //析构释放信号量
    }

    //生产
    void Push(const T& data)
    {
        this->P(_blank_sem);
        _q[_p_pos] = data;
        this->V(_data_sem);

        //下一次生产
        _p_pos++;
        _p_pos %= _cap;
    
    }


    //消费
    void Pop(T& data)
    {
        this->P(_data_sem);
        data = _q[_c_pos];
        this->V(_blank_sem);
    
        //下一次消费
        _c_pos++;
        _c_pos %= _cap;
    }
};